#pragma once
#include "Common.hpp"
#include "ThreadCache.h"
#include "PageCache.h"
#include "Fixed_LengthPool.hpp"

// 我们日常使用的malloc free都不需要创建对象，以及用对象去调用申请释放函数
// 所以在这里提供了申请和释放内存函数，在这里面封装了创建线程局部存储对象，以及调用函数的操作。

// 申请内存
void *ConcurrentAllocate(size_t size)
{
    // 小于256KB的空间申请
    if (size <= MAX_BYTES)
    {
        if (pTLSThreadCache == nullptr)
        {
            FLPool<ThreadCache> ThreadPoll;
            pTLSThreadCache = ThreadPoll.New();
        }
        return pTLSThreadCache->Allocate(size);
    }
    // 大于256KB的空间申请
    else
    {
        // 将内存对齐并计算要申请多少页的内存
        size_t alignSize = UtilClass::RoundUp(size);
        size_t npage = alignSize >> PAGE_SHIFT;
        pthread_mutex_lock(&(PageCache::GetInstance()->GetMtx())); // 加页缓存锁
        Span *span = PageCache::GetInstance()->FetchFromPageCache(npage);
        pthread_mutex_unlock(&(PageCache::GetInstance()->GetMtx())); // 解页缓存锁

        // 更新span属性
        span->objSize = size;
        span->_isUse = true;

        return (void *)(span->_pageID << PAGE_SHIFT);
    }
}

// 释放内存
void ConcurrentDeallocate(void *ptr)
{
    Span *span = PageCache::GetInstance()->MapAddressToSpan(ptr);
    size_t size = span->objSize;
    // 小于256KB的空间释放
    if (size <= MAX_BYTES)
    {
        pTLSThreadCache->Deallocate(ptr, size);
    }
    // 大于256KB空间的释放
    else
    {
        pthread_mutex_lock(&(PageCache::GetInstance()->GetMtx())); // 加页缓存锁
        PageCache::GetInstance()->ReleaseSpanToRageCache(span);
        pthread_mutex_unlock(&(PageCache::GetInstance()->GetMtx())); // 解页缓存锁
    }
}